package com.sjt.blog.service;


import com.alibaba.fastjson.JSON;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyun.oss.model.PutObjectResult;
import com.sjt.blog.vo.OssCallbackParam;
import com.sjt.blog.vo.OssCallbackResult;
import com.sjt.blog.vo.OssPolicyResult;
import com.sjt.blog.vo.OssUploadResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

@Service
public class OssServiceImpl implements OssService {
    private static final Logger LOGGER = LoggerFactory.getLogger(OssServiceImpl.class);

    @Value("${aliyun.oss.endPoint}")
    private String ALIYUN_OSS_ENDPOINT;
    @Value("${aliyun.oss.bucketName}")
    private String ALIYUN_OSS_BUCKETNAME;
    @Value("${aliyun.oss.accessKeyId}")
    private String ALIYUN_OSS_ACCESSKRYID;

    @Value("${aliyun.oss.dir.prefix}")
    private String ALIYUN_OSS_DIR_PREFIX;

    @Value("${aliyun.oss.policy.expire}")
    private int ALIYUN_OSS_EXPIRE;
    @Value("${aliyun.oss.maxSize}")
    private int ALIYUN_OSS_MAX_SIZE;
    @Value("${aliyun.oss.callback}")
    private String ALIYUN_OSS_CALLBACK;

    @Autowired
    private OSS ossClient;

    // 签名，封装完成后传到前端
    @Override
    public OssPolicyResult policy() {
        OssPolicyResult result = new OssPolicyResult();
        // 存储目录 前缀下，再新建目录，目录名为日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dir = ALIYUN_OSS_DIR_PREFIX + sdf.format(new Date());
        // 签名有效期 在配置文件中配置
        long expireEndTime = System.currentTimeMillis() + ALIYUN_OSS_EXPIRE * 1000;
        Date expiration = new Date(expireEndTime);
        // 文件大小 在配置文件中配置
        long maxSize = ALIYUN_OSS_MAX_SIZE * 1024 * 1024;
        // 回调，上传完后OSS访问后端，
        OssCallbackParam callback = new OssCallbackParam();
        callback.setCallbackUrl(ALIYUN_OSS_CALLBACK);
        callback.setCallbackBody("filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
        callback.setCallbackBodyType("application/x-www-form-urlencoded"); // 回调参数类型为表单
        // 提交节点
        String action = "http://" + ALIYUN_OSS_BUCKETNAME + "." + ALIYUN_OSS_ENDPOINT;
        try {
            // 生成凭证
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            // 凭证加密
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String policy = BinaryUtil.toBase64String(binaryData);
            String signature = ossClient.calculatePostSignature(postPolicy);
            String callbackData = BinaryUtil.toBase64String(JSON.toJSON(callback).toString().getBytes("utf-8"));
            // 签名信息封装返回
            result.setAccessKeyId(ALIYUN_OSS_ACCESSKRYID);
            result.setPolicy(policy);
            result.setSignature(signature);
            result.setDir(dir);
            result.setCallback(callbackData);
            result.setHost(action);
        } catch (Exception e) {
            LOGGER.error("签名生成失败", e);
        }
        return result;
    }


    // 回调方法 OSS请求后端，
    @Override
    public OssCallbackResult callback(HttpServletRequest request) {
        OssCallbackResult result = new OssCallbackResult();
        String filename = request.getParameter("filename");
        filename = "http://".concat(ALIYUN_OSS_BUCKETNAME).concat(".").concat(ALIYUN_OSS_ENDPOINT).concat("/").concat(filename);
        result.setFilename(filename);
        result.setSize(request.getParameter("size"));
        result.setMimeType(request.getParameter("mimeType"));
        result.setWidth(request.getParameter("width"));
        result.setHeight(request.getParameter("height"));
        return result;
    }

    @Override
    public String upload(MultipartFile file) {

        if (file.isEmpty()) {
            return null;
        }
        // 存储目录 前缀下，再新建目录，目录名为日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dir = ALIYUN_OSS_DIR_PREFIX + sdf.format(new Date());

        String filename = file.getOriginalFilename();
        System.out.println("源文件名：" + filename);

        String url = null;
        // 上传
        try {
            InputStream inputStream = file.getInputStream();
            ossClient.putObject(ALIYUN_OSS_BUCKETNAME, dir + "/" + filename, inputStream);
            // 上传完成后 拼接访问地址
            url = "http://"
                    + ALIYUN_OSS_BUCKETNAME
                    + "."
                    + ALIYUN_OSS_ENDPOINT
                    + "/"
                    + dir + "/" + filename
                    + "?x-oss-process=image";
        } catch (IOException e) {
            e.printStackTrace();
        }

        return url;
    }


}